import {
  AmcaxRender,
  EntityManager,
  PointsEntity,
  THREE,
} from '@amcax/web-render';
import { useRenderStore } from '../store';
import { ManagerId } from 'nextcae-base';

export enum PointEnum {
  TEMPP = 'tempPoint', // 临时点
  PARAMP = 'paramPoint', // 参数化的点,
  MOVEP = 'movePoint',
}
/**
 * 点的渲染样式：
 * 0  空心方框；
 * 1  十字架；
 * 2  实心圆；
 */
type PointRenderType = 0 | 1 | 2;
export default class ExtraPoints {
  private renderer: {
    mainRenderer: AmcaxRender;
    camera: THREE.PerspectiveCamera | THREE.OrthographicCamera;
    assisMgr: EntityManager;
  };
  private static instance: ExtraPoints;
  constructor() {
    this.renderer = this.getMainRenderer();
  }
  private getMainRenderer(managerId: ManagerId = ManagerId.Assis) {
    const mainRenderer = useRenderStore.getState().mainRenderer;
    return {
      mainRenderer,
      camera: mainRenderer.cameraManager.camera,
      assisMgr: mainRenderer.getEntityManager(managerId),
    };
  }
  private create(
    vertexes: (THREE.Vector3 | THREE.Vector3Tuple)[],
    key: PointEnum = PointEnum.TEMPP,
    renderType: PointRenderType = 0,
    pointSize: number = 20,
  ) {
    const vs = this.formatPoints(vertexes);
    const length = vertexes.length;
    // 创建点的Entity（多个点在一个Entity中）
    const ids = new Uint32Array(length); // id数组
    const position = new Float32Array(length * 3); // 坐标[x,y,z,x,y,z]，所以长度是3*length
    const types = new Uint8Array(length);
    for (let i = 0; i < length; i++) {
      ids[i] = i;
      position.set(vs[i], i * 3);
      types[i] = renderType;
    }
    const pointEntity = new PointsEntity(key, ids, position, types, {
      pointSize,
    });
    pointEntity.setDepthTest(false);
    return pointEntity;
  }
  static getInstance(): ExtraPoints {
    if (!this.instance) {
      this.instance = new ExtraPoints();
    }
    return this.instance;
  }
  renderPoints(
    vertexes: (THREE.Vector3 | THREE.Vector3Tuple)[],
    key: PointEnum = PointEnum.TEMPP,
    assisMgr?: EntityManager,
    renderType: PointRenderType = 0,
    pointSize: number = 20,
  ) {
    // 暂时 直接清除老的，然后插入新的；会出现闪烁，待优化
    (assisMgr ?? this.renderer.assisMgr).removeEntity(key);
    const pointEntity = this.create(vertexes, key, renderType, pointSize);
    (assisMgr ?? this.renderer.assisMgr).addEntity(pointEntity);
    this.renderer.mainRenderer.render();
  }
  renderMovePoints(
    vertexes: (THREE.Vector3 | THREE.Vector3Tuple)[],
    key: PointEnum = PointEnum.MOVEP,
    assisMgr?: EntityManager,
    renderType: PointRenderType = 0,
  ) {
    this.renderPoints(vertexes, key, assisMgr, renderType);
  }
  removePoints(key?: PointEnum, assisMgr?: EntityManager) {
    if (key) {
      (assisMgr ?? this.renderer.assisMgr).removeEntity([key]);
    } else {
      (assisMgr ?? this.renderer.assisMgr).removeEntity([
        PointEnum.TEMPP,
        PointEnum.PARAMP,
        PointEnum.MOVEP,
      ]);
    }
    this.renderer.mainRenderer.render();
  }
  formatPoints(vertexes: (THREE.Vector3 | THREE.Vector3Tuple)[]) {
    return vertexes.map((v) => {
      if (v instanceof THREE.Vector3) {
        return v.toArray();
      } else {
        return v;
      }
    });
  }
}

export const pointsManager = () => {
  return ExtraPoints.getInstance();
};
